<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta content="Cask Data, Inc." name="author" />
<meta content="Copyright © 2014-2019 Cask Data, Inc." name="copyright" />


    <meta name="git_release" content="6.1.1">
    <meta name="git_hash" content="05fbac36f9f7aadeb44f5728cea35136dbc243e5">
    <meta name="git_timestamp" content="2020-02-09 08:22:47 +0800">
    <title>Services</title>

    <link rel="stylesheet" href="../_static/cdap-bootstrap.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    <link rel="stylesheet" href="../_static/bootstrap-3.3.6/css/bootstrap.min.css" type="text/css" />
    <link rel="stylesheet" href="../_static/bootstrap-3.3.6/css/bootstrap-theme.min.css" type="text/css" />
    <link rel="stylesheet" href="../_static/css/bootstrap-sphinx.css" type="text/css" />
    <link rel="stylesheet" href="../_static/css/cdap-dynamicscrollspy-4.css" type="text/css" />
    <link rel="stylesheet" href="../_static/css/jquery.mCustomScrollbar.css" type="text/css" />
    <link rel="stylesheet" href="../_static/css/cdap-jquery.mCustomScrollbar.css" type="text/css" />
    <link rel="stylesheet" href="../_static/css/abixTreeList-2.css" type="text/css" />
    <link rel="stylesheet" href="../_static/cdap-bootstrap.css" type="text/css" />

    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '',
        VERSION:     '6.1.1',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  false
      };
    </script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <script type="text/javascript" src="../_static/language_data.js"></script>

    <link rel="shortcut icon" href="../_static/favicon.ico"/>
    <link rel="index" title="Index" href="../genindex.html" />
    <link rel="search" title="Search" href="../search.html" />
    <link rel="top" title="Cask Data Application Platform 6.1.1 Documentation" href="../index.html" />
    <link rel="up" title="核心概念" href="index.html" />
    <link rel="next" title="Spark Programs" href="spark-programs.html" />
    <link rel="prev" title="Secure Keys" href="secure-keys.html" />
    <!-- block extrahead -->
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
    <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1'>
    <meta name="apple-mobile-web-app-capable" content="yes">
    <!-- block extrahead end -->

</head>
<body role="document">

<!-- block navbar -->
<div id="navbar" class="navbar navbar-inverse navbar-default navbar-fixed-top">
    <div class="container-fluid">
      <div class="row">
        <div class="navbar-header">
          <!-- .btn-navbar is used as the toggle for collapsed navbar content -->
          <a class="navbar-brand" href="../table-of-contents/../../index.html">
            <span><img alt="CDAP logo" src="../_static/cdap_logo.svg"/></span>
          </a>

          <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".nav-collapse">
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>

          <div class="pull-right">
            <div class="dropdown version-dropdown">
              <a href="#" class="dropdown-toggle" data-toggle="dropdown"
                role="button" aria-haspopup="true" aria-expanded="false">
                v 6.1.1 <span class="caret"></span>
              </a>
              <ul class="dropdown-menu">
                <li><a href="//docs.cdap.io/cdap/5.1.2/en/index.html">v 5.1.2</a></li>
                <li><a href="//docs.cdap.io/cdap/4.3.4/en/index.html">v 4.3.4</a></li>
              </ul>
            </div>
          </div>
          <form class="navbar-form navbar-right navbar-search" action="../search.html" method="get">
            <div class="form-group">
              <div class="navbar-search-image material-icons"></div>
              <input type="text" name="q" class="form-control" placeholder="  Search" />
            </div>
            <input type="hidden" name="check_keywords" value="yes" />
            <input type="hidden" name="area" value="default" />
          </form>

          <div class="collapse navbar-collapse nav-collapse navbar-right navbar-navigation">
            <ul class="nav navbar-nav"><li class="docsite-nav-tab-container"><a class="docsite-nav-tab-link " href="../table-of-contents/../../index.html">简介</a></li><li class="docsite-nav-tab-container"><a class="docsite-nav-tab-link current" href="../table-of-contents/../../guides.html">手册</a></li><li class="docsite-nav-tab-container"><a class="docsite-nav-tab-link " href="../table-of-contents/../../reference-manual/index.html">参考</a></li><li class="docsite-nav-tab-container"><a class="docsite-nav-tab-link " href="../table-of-contents/../../faqs/index.html">帮助</a></li>
            </ul>
          </div>

        </div>
      </div>
    </div>
  </div><!-- block navbar end -->
<!-- block main content -->
<div class="main-container container">
  <div class="row"><div class="col-md-2">
      <div id="sidebar" class="bs-sidenav scrollable-y-outside" role="complementary">
<!-- theme_manual: developer-manual -->
<!-- theme_manual_highlight: guides -->
<!-- sidebar_title_link: ../table-of-contents/../../guides.html -->

  <div role="note" aria-label="manuals links"><h3><a href="../table-of-contents/../../guides.html">Guides</a></h3>

    <ul class="this-page-menu">
      <li class="toctree-l1"><a href="../table-of-contents/../../user-guide/index.html" rel="nofollow">用户手册</a>
      </li>
      <li class="toctree-l1"><b><a href="../table-of-contents/../../developer-manual/index.html" rel="nofollow">开发手册</a></b>
      <nav class="pagenav">
      <ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../index.html"> 简介</a></li>
<li class="toctree-l1"><a class="reference internal" href="../getting-started/index.html"> 入门指南</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../getting-started/sandbox/index.html">CDAP Sandbox</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../getting-started/sandbox/zip.html">二进制 Zip 文件</a></li>
<li class="toctree-l3"><a class="reference internal" href="../getting-started/sandbox/zip.html#cdap-sandbox">启动和停止 CDAP Sandbox</a></li>
<li class="toctree-l3"><a class="reference internal" href="../getting-started/sandbox/virtual-machine.html">虚拟机镜像</a></li>
<li class="toctree-l3"><a class="reference internal" href="../getting-started/sandbox/docker.html">Docker 镜像</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../getting-started/quick-start.html">快速入门</a></li>
<li class="toctree-l2"><a class="reference internal" href="../getting-started/dev-env.html">搭建开发环境</a></li>
<li class="toctree-l2"><a class="reference internal" href="../getting-started/start-stop-cdap.html">启动和停止 CDAP</a></li>
<li class="toctree-l2"><a class="reference internal" href="../getting-started/building-apps.html">构建并运行应用</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../overview/index.html"> 概述</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../overview/anatomy.html"> 大数据应用剖析</a></li>
<li class="toctree-l2"><a class="reference internal" href="../overview/modes.html"> 模式和组件</a></li>
<li class="toctree-l2"><a class="reference internal" href="../overview/abstractions.html"> 核心概念</a></li>
<li class="toctree-l2"><a class="reference internal" href="../overview/interfaces.html"> 编程接口</a></li>
</ul>
</li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html"> 抽象概念</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="core.html"> Core Abstractions</a></li>
<li class="toctree-l2"><a class="reference internal" href="applications.html"> Applications</a></li>
<li class="toctree-l2"><a class="reference internal" href="datasets/index.html"> Datasets</a><ul>
<li class="toctree-l3"><a class="reference internal" href="datasets/overview.html"> Overview</a></li>
<li class="toctree-l3"><a class="reference internal" href="datasets/table.html"> Table API</a></li>
<li class="toctree-l3"><a class="reference internal" href="datasets/fileset.html"> FileSets</a></li>
<li class="toctree-l3"><a class="reference internal" href="datasets/partitioned-fileset.html"> Partitioned FileSets</a></li>
<li class="toctree-l3"><a class="reference internal" href="datasets/time-partitioned-fileset.html"> TimePartitioned FileSets</a></li>
<li class="toctree-l3"><a class="reference internal" href="datasets/system-custom.html"> System and Custom Datasets</a></li>
<li class="toctree-l3"><a class="reference internal" href="datasets/permissions.html"> Dataset Permissions</a></li>
<li class="toctree-l3"><a class="reference internal" href="datasets/cube.html"> Cube Dataset</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="mapreduce-programs.html"> MapReduce Programs</a></li>
<li class="toctree-l2"><a class="reference internal" href="plugins.html"> Plugins</a></li>
<li class="toctree-l2"><a class="reference internal" href="schedules.html"> Schedules</a></li>
<li class="toctree-l2"><a class="reference internal" href="secure-keys.html"> Secure Keys</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#"> Services</a></li>
<li class="toctree-l2"><a class="reference internal" href="spark-programs.html"> Spark Programs</a></li>
<li class="toctree-l2"><a class="reference internal" href="workers.html"> Workers</a></li>
<li class="toctree-l2"><a class="reference internal" href="workflows.html"> Workflows</a></li>
<li class="toctree-l2"><a class="reference internal" href="artifacts.html"> Artifacts</a></li>
<li class="toctree-l2"><a class="reference internal" href="program-lifecycle.html"> Program Lifecycle</a></li>
<li class="toctree-l2"><a class="reference internal" href="namespaces.html"> Namespaces</a></li>
<li class="toctree-l2"><a class="reference internal" href="transaction-system.html"> Transaction System</a></li>
<li class="toctree-l2"><a class="reference internal" href="transactional-messaging-system.html"> Transactional Messaging System</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../metadata/index.html"> 元数据</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../metadata/system-metadata.html"> System Metadata</a></li>
<li class="toctree-l2"><a class="reference internal" href="../metadata/discovery-lineage.html"> Discovery and Lineage</a></li>
<li class="toctree-l2"><a class="reference internal" href="../metadata/field-lineage.html"> Field Level Lineage</a></li>
<li class="toctree-l2"><a class="reference internal" href="../metadata/audit-logging.html"> Audit Logging</a></li>
<li class="toctree-l2"><a class="reference internal" href="../metadata/metadata-ui.html"> CDAP Metadata UI</a></li>
<li class="toctree-l2"><a class="reference internal" href="../metadata/programmatic-metadata.html"> Accessing metadata programmatically</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../pipelines/index.html"> 数据流管道</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../pipelines/concepts-design.html"> Concepts and Design</a></li>
<li class="toctree-l2"><a class="reference internal" href="../pipelines/getting-started.html"> Getting Started</a></li>
<li class="toctree-l2"><a class="reference internal" href="../pipelines/studio.html"> CDAP Studio</a></li>
<li class="toctree-l2"><a class="reference internal" href="../pipelines/creating-pipelines.html"> Creating Pipelines</a></li>
<li class="toctree-l2"><a class="reference internal" href="../pipelines/running-pipelines.html"> Running Pipelines</a></li>
<li class="toctree-l2"><a class="reference internal" href="../pipelines/plugin-management.html"> Plugin Management</a></li>
<li class="toctree-l2"><a class="reference internal" href="../pipelines/plugins/index.html"> Plugin Reference</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../pipelines/plugins/actions/index.html"> Action Plugins</a><ul class="simple">
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="../pipelines/plugins/sources/index.html"> Source Plugins</a><ul class="simple">
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="../pipelines/plugins/transforms/index.html"> Transform Plugins</a><ul class="simple">
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="../pipelines/plugins/analytics/index.html"> Analytic Plugins</a><ul class="simple">
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="../pipelines/plugins/sinks/index.html"> Sink Plugins</a><ul class="simple">
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="../pipelines/plugins/shared-plugins/index.html"> Shared Plugins</a><ul>
<li class="toctree-l4"><a class="reference internal" href="../pipelines/plugins/shared-plugins/core.html">CoreValidator</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="../pipelines/plugins/post-run-plugins/index.html"> Post-run Plugins</a><ul class="simple">
</ul>
</li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../pipelines/developing-pipelines.html"> Developing Pipelines</a></li>
<li class="toctree-l2"><a class="reference internal" href="../pipelines/developing-plugins/index.html"> Developing Plugins</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../pipelines/developing-plugins/plugin-basics.html">Plugin Basics</a></li>
<li class="toctree-l3"><a class="reference internal" href="../pipelines/developing-plugins/creating-a-plugin.html">Creating a Plugin</a></li>
<li class="toctree-l3"><a class="reference internal" href="../pipelines/developing-plugins/presentation-plugins.html">Plugin Presentation</a></li>
<li class="toctree-l3"><a class="reference internal" href="../pipelines/developing-plugins/testing-plugins.html">Testing Plugins</a></li>
<li class="toctree-l3"><a class="reference internal" href="../pipelines/developing-plugins/packaging-plugins.html">Packaging Plugins</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../pipelines/how-cdap-pipelines-work.html"> How CDAP Pipelines Work</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../cloud-runtimes/index.html"> 云平台运行</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../cloud-runtimes/concepts/index.html"> Concepts</a></li>
<li class="toctree-l2"><a class="reference internal" href="../cloud-runtimes/provisioners/index.html"> Provisioners</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../cloud-runtimes/provisioners/gcp-dataproc.html">Google Dataproc</a></li>
<li class="toctree-l3"><a class="reference internal" href="../cloud-runtimes/provisioners/aws-emr.html">Amazon Elastic MapReduce</a></li>
<li class="toctree-l3"><a class="reference internal" href="../cloud-runtimes/provisioners/remote-hadoop.html">Remote Hadoop</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../cloud-runtimes/profiles/index.html"> Profiles</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../cloud-runtimes/profiles/creating-profiles.html">Creating Profiles</a></li>
<li class="toctree-l3"><a class="reference internal" href="../cloud-runtimes/profiles/assigning-profiles.html">Assigning Profiles</a></li>
<li class="toctree-l3"><a class="reference internal" href="../cloud-runtimes/profiles/admin-controls.html">Admin Controls</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../cloud-runtimes/example/index.html"> Example</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../security/index.html"> 安全</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../security/client-authentication.html">Client Authentication</a></li>
<li class="toctree-l2"><a class="reference internal" href="../security/cdap-authentication-clients-java.html">CDAP Authentication Client for Java</a></li>
<li class="toctree-l2"><a class="reference internal" href="../security/cdap-authentication-clients-python.html">CDAP Authentication Client for Python</a></li>
<li class="toctree-l2"><a class="reference internal" href="../security/custom-authentication.html">Custom Authentication</a></li>
<li class="toctree-l2"><a class="reference internal" href="../security/authorization-extensions.html">Authorization Extensions</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../testing/index.html"> 测试和调试</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../testing/testing.html"> Testing a CDAP Application</a></li>
<li class="toctree-l2"><a class="reference internal" href="../testing/debugging.html"> Debugging</a></li>
<li class="toctree-l2"><a class="reference internal" href="../testing/troubleshooting.html"> Troubleshooting</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../ingesting-tools/index.html"> 数据融合</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../ingesting-tools/cdap-stream-clients-java.html">CDAP Stream Client for Java</a></li>
<li class="toctree-l2"><a class="reference internal" href="../ingesting-tools/cdap-stream-clients-python.html">CDAP Stream Client for Python</a></li>
<li class="toctree-l2"><a class="reference internal" href="../ingesting-tools/cdap-stream-clients-ruby.html">CDAP Stream Client for Ruby</a></li>
<li class="toctree-l2"><a class="reference internal" href="../ingesting-tools/cdap-flume.html">CDAP Flume</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../data-exploration/index.html"> 数据探索</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../data-exploration/filesets.html"> Fileset Exploration</a></li>
<li class="toctree-l2"><a class="reference internal" href="../data-exploration/tables.html"> Table Exploration</a></li>
<li class="toctree-l2"><a class="reference internal" href="../data-exploration/object-mapped-tables.html"> ObjectMappedTable Exploration</a></li>
<li class="toctree-l2"><a class="reference internal" href="../data-exploration/custom-datasets.html"> Custom Dataset Exploration</a></li>
<li class="toctree-l2"><a class="reference internal" href="../data-exploration/hive-execution-engines.html"> Hive Execution Engines</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../advanced/index.html"> 高级主题</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../advanced/application-logback.html"> Application Logback</a></li>
<li class="toctree-l2"><a class="reference internal" href="../advanced/best-practices.html"> Best Practices</a></li>
<li class="toctree-l2"><a class="reference internal" href="../advanced/class-loading.html"> Class Loading</a></li>
<li class="toctree-l2"><a class="reference internal" href="../advanced/configuring-resources.html"> Configuring Program Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../advanced/program-retry-policies.html"> Program Retry Policies</a></li>
</ul>
</li>
</ul>
</nav>
      </li>
      <li class="toctree-l1"><a href="../table-of-contents/../../admin-manual/index.html" rel="nofollow">管理手册</a>
      </li>
      <li class="toctree-l1"><a href="../table-of-contents/../../integrations/index.html" rel="nofollow">集成手册</a>
      </li>
      <li class="toctree-l1"><a href="../table-of-contents/../../examples-manual/index.html" rel="nofollow">最佳实践</a>
      </li>
    </ul>
  </div></div>
    </div><div class="col-md-8 content" id="main-content">
    
  <div class="section" id="services">
<span id="user-services"></span><h1>Services<a class="headerlink" href="#services" title="Permalink to this headline">🔗</a></h1>
<p><em>Services</em> can be run in a Cask Data Application Platform (CDAP) application to serve data to external clients.
Similar to flows, services run in containers and the number of running service instances can be dynamically scaled.
Developers can implement custom services to interface with a legacy system and perform additional processing beyond
the CDAP processing paradigms. Examples could include running an IP-to-geo lookup and serving user-profiles.</p>
<p>The lifecycle of a custom service can be controlled via the CDAP UI, by using the
<span class="xref std std-ref">CDAP Java Client API</span>, or with the <span class="xref std std-ref">CDAP RESTful HTTP API</span>.</p>
<p>You can add services to your application by calling the <code class="docutils literal notranslate"><span class="pre">addService</span></code> method in the
application’s <code class="docutils literal notranslate"><span class="pre">configure</span></code> method:</p>
<div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">AnalyticsApp</span> <span class="kd">extends</span> <span class="n">AbstractApplication</span> <span class="p">{</span>
  <span class="nd">@Override</span>
  <span class="kd">public</span> <span class="kt">void</span> <span class="nf">configure</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">setName</span><span class="p">(</span><span class="s">&quot;AnalyticsApp&quot;</span><span class="p">);</span>
    <span class="n">setDescription</span><span class="p">(</span><span class="s">&quot;Application for generating mobile analytics&quot;</span><span class="p">);</span>
    <span class="n">addStream</span><span class="p">(</span><span class="k">new</span> <span class="n">Stream</span><span class="p">(</span><span class="s">&quot;event&quot;</span><span class="p">));</span>
    <span class="n">addFlow</span><span class="p">(</span><span class="k">new</span> <span class="n">EventProcessingFlow</span><span class="p">());</span>
    <span class="p">...</span>
    <span class="n">addService</span><span class="p">(</span><span class="k">new</span> <span class="n">IPGeoLookupService</span><span class="p">());</span>
    <span class="n">addService</span><span class="p">(</span><span class="k">new</span> <span class="n">UserLookupService</span><span class="p">());</span>
    <span class="p">...</span>
  <span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Services are implemented by extending <code class="docutils literal notranslate"><span class="pre">AbstractService</span></code>, which consists of
<code class="docutils literal notranslate"><span class="pre">HttpServiceHandler</span></code>s to serve requests:</p>
<div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">IPGeoLookupService</span> <span class="kd">extends</span> <span class="n">AbstractService</span> <span class="p">{</span>

  <span class="nd">@Override</span>
  <span class="kd">protected</span> <span class="kt">void</span> <span class="nf">configure</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">setName</span><span class="p">(</span><span class="s">&quot;IpGeoLookupService&quot;</span><span class="p">);</span>
    <span class="n">setDescription</span><span class="p">(</span><span class="s">&quot;Service to lookup locations of IP addresses.&quot;</span><span class="p">);</span>
    <span class="n">useDataset</span><span class="p">(</span><span class="s">&quot;IPGeoTable&quot;</span><span class="p">);</span>
    <span class="n">addHandler</span><span class="p">(</span><span class="k">new</span> <span class="n">IPGeoLookupHandler</span><span class="p">());</span>
  <span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<div class="section" id="service-handlers">
<span id="user-service-handlers"></span><h2>Service Handlers<a class="headerlink" href="#service-handlers" title="Permalink to this headline">🔗</a></h2>
<p><code class="docutils literal notranslate"><span class="pre">ServiceHandler</span></code>s are used to handle and serve HTTP requests.</p>
<p>You add handlers to your service by calling the <code class="docutils literal notranslate"><span class="pre">addHandler</span></code> method in the service’s
<code class="docutils literal notranslate"><span class="pre">configure</span></code> method, as shown above. Only handler classes that are declared public,
with public methods for endpoints, will be exposed by the service.</p>
<p>To use a dataset within a handler, either include the <code class="docutils literal notranslate"><span class="pre">&#64;UseDataSet</span></code> annotation in
the handler, or use the <code class="docutils literal notranslate"><span class="pre">getDataset()</span></code> method dynamically in the handler to obtain
an instance of the dataset (see <a class="reference internal" href="datasets/overview.html#datasets-in-programs"><span class="std std-ref">Using Datasets in Programs</span></a>).
Each request to a method is committed as a single transaction.</p>
<div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">IPGeoLookupHandler</span> <span class="kd">extends</span> <span class="n">AbstractHttpServiceHandler</span> <span class="p">{</span>
  <span class="nd">@UseDataSet</span><span class="p">(</span><span class="s">&quot;IPGeoTable&quot;</span><span class="p">)</span>
  <span class="n">Table</span> <span class="n">table</span><span class="p">;</span>

  <span class="nd">@Path</span><span class="p">(</span><span class="s">&quot;lookup/{ip}&quot;</span><span class="p">)</span>
  <span class="nd">@GET</span>
  <span class="kd">public</span> <span class="kt">void</span> <span class="nf">lookup</span><span class="p">(</span><span class="n">HttpServiceRequest</span> <span class="n">request</span><span class="p">,</span> <span class="n">HttpServiceResponder</span> <span class="n">responder</span><span class="p">,</span>
                                                    <span class="nd">@PathParam</span><span class="p">(</span><span class="s">&quot;ip&quot;</span><span class="p">)</span> <span class="n">String</span> <span class="n">ip</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>
    <span class="n">responder</span><span class="p">.</span><span class="na">sendString</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="n">location</span><span class="p">,</span> <span class="n">Charsets</span><span class="p">.</span><span class="na">UTF_8</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="path-and-query-parameters">
<h2>Path and Query Parameters<a class="headerlink" href="#path-and-query-parameters" title="Permalink to this headline">🔗</a></h2>
<p>Handler endpoints can have Path and Query parameters. Path parameters are used to assist with path-mapping of requests,
while Query parameters are used to easily parse the query string of a request.</p>
<p>For example, the <code class="docutils literal notranslate"><span class="pre">WordCount</span></code> application has a <code class="docutils literal notranslate"><span class="pre">Service</span></code> that exposes an endpoint to retrieve the count of a word
and its word associations. In the <code class="docutils literal notranslate"><span class="pre">&#64;Path</span></code> annotation, <code class="docutils literal notranslate"><span class="pre">{word}</span></code> is a path parameter that is mapped
to a Java String using <code class="docutils literal notranslate"><span class="pre">&#64;PathParam(&quot;word&quot;)</span> <span class="pre">String</span> <span class="pre">word</span></code>. Similarly, the endpoint also allows
the query parameter <code class="docutils literal notranslate"><span class="pre">limit</span></code> with a default value of 10.</p>
<div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="nd">@Path</span><span class="p">(</span><span class="s">&quot;count/{word}&quot;</span><span class="p">)</span>
<span class="nd">@GET</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">getCount</span><span class="p">(</span><span class="n">HttpServiceRequest</span> <span class="n">request</span><span class="p">,</span> <span class="n">HttpServiceResponder</span> <span class="n">responder</span><span class="p">,</span>
                     <span class="nd">@PathParam</span><span class="p">(</span><span class="s">&quot;word&quot;</span><span class="p">)</span> <span class="n">String</span> <span class="n">word</span><span class="p">,</span>
                     <span class="nd">@QueryParam</span><span class="p">(</span><span class="s">&quot;limit&quot;</span><span class="p">)</span> <span class="nd">@DefaultValue</span><span class="p">(</span><span class="s">&quot;10&quot;</span><span class="p">)</span> <span class="n">Integer</span> <span class="n">limit</span><span class="p">)</span> <span class="p">{</span>

  <span class="c1">// ...</span>
<span class="p">}</span>
</pre></div>
</div>
<p>An example of calling this endpoint with the HTTP RESTful API is shown in the <span class="xref std std-ref">http-restful-api-service</span>.</p>
<p><strong>Note:</strong> Any reserved or unsafe characters in the path parameters should be encoded using
<span class="xref std std-ref">percent-encoding</span>.
See the next section, <a class="reference internal" href="#services-path-parameters"><span class="std std-ref">About Path Parameters</span></a>.</p>
</div>
<div class="section" id="handling-a-large-request-body">
<span id="services-content-consumer"></span><h2>Handling a Large Request Body<a class="headerlink" href="#handling-a-large-request-body" title="Permalink to this headline">🔗</a></h2>
<p>Sometimes the request body for a <code class="docutils literal notranslate"><span class="pre">PUT</span></code> or <code class="docutils literal notranslate"><span class="pre">POST</span></code> request can be huge and it is not feasible to keep all
of it in memory. You can have the handler method return an <code class="docutils literal notranslate"><span class="pre">HttpContentConsumer</span></code> instead of <code class="docutils literal notranslate"><span class="pre">void</span></code>
to process the request body in smaller pieces.</p>
<p>For example, the <code class="docutils literal notranslate"><span class="pre">SportResults</span></code> application has an <code class="docutils literal notranslate"><span class="pre">UploadService</span></code> that exposes an endpoint for uploading files
to <code class="docutils literal notranslate"><span class="pre">PartitionedFileSets</span></code>. It returns an <code class="docutils literal notranslate"><span class="pre">HttpContentConsumer</span></code> so that it receives the request body in a series
of small chunks:</p>
<div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="nd">@PUT</span>
<span class="nd">@Path</span><span class="p">(</span><span class="s">&quot;leagues/{league}/seasons/{season}&quot;</span><span class="p">)</span>
<span class="kd">public</span> <span class="n">HttpContentConsumer</span> <span class="nf">write</span><span class="p">(</span><span class="n">HttpServiceRequest</span> <span class="n">request</span><span class="p">,</span> <span class="n">HttpServiceResponder</span> <span class="n">responder</span><span class="p">,</span>
                                 <span class="nd">@PathParam</span><span class="p">(</span><span class="s">&quot;league&quot;</span><span class="p">)</span> <span class="n">String</span> <span class="n">league</span><span class="p">,</span> <span class="nd">@PathParam</span><span class="p">(</span><span class="s">&quot;season&quot;</span><span class="p">)</span> <span class="kt">int</span> <span class="n">season</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// ...</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="about-path-parameters">
<span id="services-path-parameters"></span><h2>About Path Parameters<a class="headerlink" href="#about-path-parameters" title="Permalink to this headline">🔗</a></h2>
<p>The value of a path parameter cannot contain any <a class="reference external" href="http://tools.ietf.org/html/rfc3986#section-2.2">characters that have a special meaning</a> in URI syntax. If a request has a path
parameter that contains such a character, it must be <a class="reference external" href="http://tools.ietf.org/html/rfc3986#section-2.1">URL-encoded</a> using the “<code class="docutils literal notranslate"><span class="pre">%hh</span></code>” notation, a
percent-symbol followed by two hex characters.</p>
<p>In general, any character that is not a letter, a digit, or one of <code class="docutils literal notranslate"><span class="pre">$-_.+!*'()</span></code> should be encoded.</p>
<p>However, if the special character is a forward-slash (<code class="docutils literal notranslate"><span class="pre">/</span></code>), then it will appear to the
path matcher as a “<code class="docutils literal notranslate"><span class="pre">/</span></code>”, even if it is escaped as “<code class="docutils literal notranslate"><span class="pre">%2f</span></code>”. This occurs because the path is
decoded prior to matching.</p>
<p>There are two ways to work around this:</p>
<ul class="simple">
<li>Double-escape any forward-slashes (<code class="docutils literal notranslate"><span class="pre">/</span></code>) as “<code class="docutils literal notranslate"><span class="pre">%252f</span></code>”. This will prevent the decoding before the path is matched.
However, the path parameter’s value will contain the “<code class="docutils literal notranslate"><span class="pre">%2f</span></code>” instead of a “<code class="docutils literal notranslate"><span class="pre">/</span></code>”, and the
application code must decode the parameter itself to obtain the actual value.</li>
<li>Use a query parameter instead. This is a better solution because the “<code class="docutils literal notranslate"><span class="pre">/</span></code>” is not a reserved
character in the query of a URI.</li>
</ul>
</div>
<div class="section" id="service-discovery">
<h2>Service Discovery<a class="headerlink" href="#service-discovery" title="Permalink to this headline">🔗</a></h2>
<p>Services announce the host and port they are running on so that they can be discovered—and
accessed—by other programs.</p>
<p>Service are announced using the name passed in the <code class="docutils literal notranslate"><span class="pre">configure</span></code> method. The <em>application name</em>, <em>service id</em>, and
<em>hostname</em> required for registering the service are automatically obtained.</p>
<p>The service can then be discovered in a flow, MapReduce, Spark, or another service using
the appropriate program context. You may also access a service in a different application
by specifying the application name in the <code class="docutils literal notranslate"><span class="pre">getServiceURL</span></code> call.</p>
<p>For example, in flows:</p>
<div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">GeoFlowlet</span> <span class="kd">extends</span> <span class="n">AbstractFlowlet</span> <span class="p">{</span>

  <span class="c1">// URL for IPGeoLookupService</span>
  <span class="kd">private</span> <span class="n">URL</span> <span class="n">serviceURL</span><span class="p">;</span>

  <span class="c1">// URL for SecurityService in SecurityApplication</span>
  <span class="kd">private</span> <span class="n">URL</span> <span class="n">securityURL</span><span class="p">;</span>

  <span class="nd">@ProcessInput</span>
  <span class="kd">public</span> <span class="kt">void</span> <span class="nf">process</span><span class="p">(</span><span class="n">String</span> <span class="n">ip</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Get URL for service in same application</span>
    <span class="n">serviceURL</span> <span class="o">=</span> <span class="n">getContext</span><span class="p">().</span><span class="na">getServiceURL</span><span class="p">(</span><span class="s">&quot;IPGeoLookupService&quot;</span><span class="p">);</span>

    <span class="c1">// Get URL for service in a different application</span>
    <span class="n">securityURL</span> <span class="o">=</span> <span class="n">getContext</span><span class="p">().</span><span class="na">getServiceURL</span><span class="p">(</span><span class="s">&quot;SecurityApplication&quot;</span><span class="p">,</span> <span class="s">&quot;SecurityService&quot;</span><span class="p">);</span>

    <span class="c1">// Access the IPGeoLookupService using its URL</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">serviceURL</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">URLConnection</span> <span class="n">connection</span> <span class="o">=</span> <span class="k">new</span> <span class="n">URL</span><span class="p">(</span><span class="n">serviceURL</span><span class="p">,</span> <span class="n">String</span><span class="p">.</span><span class="na">format</span><span class="p">(</span><span class="s">&quot;lookup/%s&quot;</span><span class="p">,</span> <span class="n">ip</span><span class="p">)).</span><span class="na">openConnection</span><span class="p">();</span>
      <span class="n">BufferedReader</span> <span class="n">reader</span> <span class="o">=</span> <span class="k">new</span> <span class="n">BufferedReader</span><span class="p">(</span><span class="k">new</span> <span class="n">InputStreamReader</span><span class="p">(</span><span class="n">connection</span><span class="p">.</span><span class="na">getInputStream</span><span class="p">()));</span>
    <span class="p">}</span>
    <span class="p">...</span>
    <span class="c1">// Access the SecurityService using its URL</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">securityURL</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
      <span class="p">...</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="services-and-resources">
<h2>Services and Resources<a class="headerlink" href="#services-and-resources" title="Permalink to this headline">🔗</a></h2>
<p>When a service is configured, the resource requirements for the server that runs all
handlers of the service can be set, both in terms of the amount of memory (in megabytes)
and the number of virtual cores assigned.</p>
<p>If both the memory and the number of cores needs to be set, this can be done using:</p>
<div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="n">setResources</span><span class="p">(</span><span class="k">new</span> <span class="n">Resources</span><span class="p">(</span><span class="mi">1024</span><span class="p">,</span> <span class="mi">2</span><span class="p">));</span>
</pre></div>
</div>
<p>The resource requirements can also be altered through runtime arguments,
as explained in <a class="reference internal" href="../advanced/configuring-resources.html#advanced-configuring-resources"><span class="std std-ref">Configuring Resources</span></a>.</p>
</div>
<div class="section" id="service-thread-model">
<h2>Service Thread Model<a class="headerlink" href="#service-thread-model" title="Permalink to this headline">🔗</a></h2>
<p>An HTTP server is started for each Service instance, which by default starts 60 threads to handle
client requests. Each thread is basically tied to one active client request and each thread would
have its own instance of <code class="docutils literal notranslate"><span class="pre">HttpServiceHandler</span></code>s. This guarantees there will be no concurrent
calls to each <code class="docutils literal notranslate"><span class="pre">HttpServiceHandler</span></code> object instance. Also, by default, when a thread is idled
for more than 60 seconds, it will be terminated automatically, with the <code class="docutils literal notranslate"><span class="pre">HttpServiceHandler.destroy</span></code>
method being called to release resources.</p>
<p>Both the number of service threads and the thread keep-alive time can be altered by these runtime arguments:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">system.service.threads</span></code>: Number of threads to use in the HTTP server</li>
<li><code class="docutils literal notranslate"><span class="pre">system.service.thread.keepalive.secs</span></code>: Number of seconds a thread can sit idle before getting terminated</li>
</ul>
</div>
<div class="section" id="services-examples">
<h2>Services Examples<a class="headerlink" href="#services-examples" title="Permalink to this headline">🔗</a></h2>
<ul class="simple">
<li>Many of the <span class="xref std std-ref">how-to guides</span> demonstrate the use of services.</li>
</ul>
</div>
</div>

</div>
    <div class="col-md-2">
      <div id="right-sidebar" class="bs-sidenav scrollable-y" role="complementary">
        <div id="localtoc-scrollspy">
        </div>
      </div>
    </div></div>
</div>
<!-- block main content end -->
<!-- block footer -->
<footer class="footer">
      <div class="container">
        <div class="row">
          <div class="col-md-2 footer-left"><a title="Secure Keys" href="secure-keys.html" />Previous</a></div>
          <div class="col-md-8 footer-center"><a class="footer-tab-link" href="../table-of-contents/../../reference-manual/licenses/index.html">Copyright</a> &copy; 2014-2020 Cask Data, Inc.&bull; <a class="footer-tab-link" href="//docs.cask.co/cdap/6.1.1/cdap-docs-6.1.1-web.zip" rel="nofollow">Download</a> an archive or
<a class="footer-tab-link" href="//docs.cask.co/cdap">switch the version</a> of the documentation
          </div>
          <div class="col-md-2 footer-right"><a title="Spark Programs" href="spark-programs.html" />Next</a></div>
        </div>
      </div>
    </footer>
<!-- block footer end -->
<script type="text/javascript" src="../_static/bootstrap-3.3.6/js/bootstrap.min.js"></script><script type="text/javascript" src="../_static/js/bootstrap-sphinx.js"></script><script type="text/javascript" src="../_static/js/abixTreeList-2.js"></script><script type="text/javascript" src="../_static/js/cdap-dynamicscrollspy-4.js"></script><script type="text/javascript" src="../_static/js/cdap-version-menu.js"></script><script type="text/javascript" src="../_static/js/copy-to-clipboard.js"></script><script type="text/javascript" src="../_static/js/jquery.mousewheel.min.js"></script><script type="text/javascript" src="../_static/js/jquery.mCustomScrollbar.js"></script><script type="text/javascript" src="../_static/js/js.cookie.js"></script><script type="text/javascript" src="../_static/js/tabbed-parsed-literal-0.2.js"></script><script type="text/javascript" src="../_static/js/cdap-onload-javascript.js"></script><script type="text/javascript" src="../_static/js/cdap-version-menu.js"></script>
    <script src="https://cdap.gitee.io/docs/cdap/json-versions.js"/></script>
  </body>
</html>